package net.oschina.git.views;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.client.ClientProtocolException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.egit.core.RepositoryUtil;
import org.eclipse.egit.ui.internal.clone.GitCreateProjectViaWizardWizard;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.InvalidRemoteException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.TransportException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.plugin.AbstractUIPlugin;

import com.google.gson.JsonArray;

import net.oschina.git.Activator;
import net.oschina.git.entity.Repositories;
import net.oschina.git.handlers.WindowsHandler;
import net.oschina.git.utils.GitUtil;
import net.oschina.git.utils.HttpUtil;
import net.oschina.git.utils.JsonUtil;
import net.oschina.git.utils.RemoteApi;
import net.oschina.git.utils.UserData;
import net.oschina.git.utils.i18n;
import org.eclipse.swt.layout.GridLayout;

public class CloneRepository extends Dialog {
	private Text pDir;// 工作目录
	private Text projectName;// 项目目录
	private Combo combo;// 所有项目
	private String projectPath;
	private String projectText;// 项目名称
	private String private_token;
	private String username;
	private String password;
	private List<String> list = null;
	protected final RepositoryUtil util = org.eclipse.egit.core.Activator.getDefault().getRepositoryUtil();
	private Text search;

	/**
	 * Create the dialog.
	 * 
	 * @param parentShell
	 * @wbp.parser.constructor
	 */
	public CloneRepository(Shell parentShell) {
		super(parentShell);
	}

	public CloneRepository(Shell parentShell, String private_token) {
		super(parentShell);
		this.private_token = private_token;
	}

	public CloneRepository(Shell parentShell, String private_token, String username, String password) {
		super(parentShell);
		this.username = username;
		this.password = password;
		this.private_token = private_token;
	}

	@Override
	protected void setShellStyle(int newShellStyle) {
		super.setShellStyle(SWT.CLOSE | SWT.MODELESS | SWT.BORDER | SWT.TITLE | SWT.RESIZE);
		setBlockOnOpen(false);
	}

	@Override
	protected void configureShell(Shell shell) {
		super.configureShell(shell);
		shell.setText(i18n.cloneRep);
		shell.setImage(AbstractUIPlugin.imageDescriptorFromPlugin(Activator.getDefault().getBundle().getSymbolicName(),
				"$nl$/icons/oschina.ico").createImage());
	}

	/**
	 * Create contents of the dialog.
	 * 
	 * @param parent
	 */
	@Override
	protected Control createDialogArea(Composite parent) {
		parent.setLayout(new GridLayout(1, false));
		final Composite container = (Composite) super.createDialogArea(parent);
		container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		GridLayout gl_container = new GridLayout(3, false);
		gl_container.verticalSpacing = 10;
		container.setLayout(gl_container);

		Label lblSearch = new Label(container, SWT.NONE);
		lblSearch.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));
		lblSearch.setText(i18n.Search + ":");

		search = new Text(container, SWT.BORDER);
		search.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 2, 1));
		search.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				String searchKey = search.getText();
				for (String str : list) {
					if (str.contains("/" + searchKey)) {
						combo.select(list.indexOf(str));
					}
				}
			}
		});
		Label url = new Label(container, SWT.NONE);
		url.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));
		url.setText(i18n.giturl + ":");
		combo = new Combo(container, SWT.READ_ONLY);
		combo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		combo.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				// TODO Auto-generated method stub
				projectName.setText(getDefaultDirName(combo.getText()));
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				// TODO Auto-generated method stub

			}

		});
		try {
			list = getRepositoriesArray().get(0).getRepositories();
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			MessageDialog.openError(parent.getShell(), "Error", e.getMessage());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			MessageDialog.openError(parent.getShell(), "Error", "Network Issues");
		}
		if (list != null) {
			String[] strarray = new String[list.size()];
			combo.setItems(list.toArray(strarray));
		}

		Button testButton = new Button(container, SWT.NONE);
		GridData gd_testButton = new GridData(SWT.LEFT, SWT.CENTER, true, true, 1, 1);
		gd_testButton.heightHint = 22;
		gd_testButton.widthHint = 58;
		testButton.setLayoutData(gd_testButton);
		testButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				try {
					String cloneType = UserData.getValue("cloneType");
					if (cloneType.equals("ssh")) {
						GitUtil.testRepBySSH(combo.getText());
					} else if (cloneType.equals("http")) {
						GitUtil.testRepByPassword(combo.getText(), username, password);
					}
					System.out.println();
					MessageDialog.openInformation(container.getShell(), "Info", "It's Ok!");
				} catch (InvalidRemoteException e1) {
					// TODO Auto-generated catch block
					MessageDialog.openError(container.getShell(), "Error", e1.getMessage());
				} catch (TransportException e1) {
					// TODO Auto-generated catch block
					MessageDialog.openError(container.getShell(), "Error", e1.getMessage());
				} catch (GitAPIException e1) {
					// TODO Auto-generated catch block
					MessageDialog.openError(container.getShell(), "Error", e1.getMessage());
				}
			}
		});
		testButton.setText(i18n.Test);

		Label parentdir = new Label(container, SWT.NONE);
		parentdir.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));
		parentdir.setText(i18n.parentdir + ":");

		pDir = new Text(container, SWT.BORDER);
		pDir.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));
		pDir.setEditable(false);
		pDir.setText(Platform.getLocation().append("/").toOSString());

		Button btnNewButton = new Button(container, SWT.NONE);
		btnNewButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));
		btnNewButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				DirectoryDialog dialog = new DirectoryDialog(container.getShell());
				dialog.setFilterPath(pDir.getText());
				String openString = dialog.open();
				if (openString != null) {
					pDir.setText(openString);
				}
			}
		});
		btnNewButton.setAlignment(SWT.LEFT);
		btnNewButton.setText("...");

		Label dirName = new Label(container, SWT.NONE);
		dirName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));
		dirName.setText(i18n.dirName + ":");

		projectName = new Text(container, SWT.BORDER);
		projectName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 2, 1));
		if (combo.getItemCount() > 0) {
			combo.select(0);
			projectName.setText(getDefaultDirName(combo.getText()));
		}

		return container;
	}

	/**
	 * Create contents of the button bar.
	 * 
	 * @param parent
	 */
	@Override
	protected void createButtonsForButtonBar(final Composite parent) {
		Button clone = createButton(parent, IDialogConstants.NO_ID, i18n.Clone, true);
		clone.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseUp(MouseEvent e) {
				if (!pDir.getText().isEmpty() && !projectName.getText().isEmpty()) {
					String cloneType = UserData.getValue("cloneType");
					final String url = combo.getText();
					projectText = projectName.getText();
					projectPath = pDir.getText() + Platform.getLocation().SEPARATOR + projectText;
					if (cloneType.equals("ssh")) {
						try {
							new ProgressMonitorDialog(parent.getShell()).run(true, true, new IRunnableWithProgress() {// 显示进度框
								@Override
								public void run(IProgressMonitor monitor)
										throws InvocationTargetException, InterruptedException {
									// TODO Auto-generated method stub
									try {
										GitUtil.cloneBySSH(projectPath, url, monitor);
									} catch (IllegalStateException e) {
										// TODO Auto-generated catch block
										MessageDialog.openError(parent.getShell(), "Error", e.getMessage());
									} catch (GitAPIException e) {
										// TODO Auto-generated catch block
										MessageDialog.openError(parent.getShell(), "Error", e.getMessage());
									}
								}

							});
						} catch (Exception e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
							// MessageDialog.openError(parent.getShell(),
							// "Error", e1.getMessage());
						}
						afterClone(parent.getShell());
					} else if (cloneType.equals("http")) {
						try {
							new ProgressMonitorDialog(parent.getShell()).run(true, true, new IRunnableWithProgress() {

								@Override
								public void run(IProgressMonitor monitor)
										throws InvocationTargetException, InterruptedException {
									// TODO Auto-generated method stub
									try {
										GitUtil.cloneByPassword(projectPath, url, username, password, monitor);
									} catch (IllegalStateException e) {
										// TODO Auto-generated catch block
										MessageDialog.openError(parent.getShell(), "Error", e.getMessage());
									} catch (JGitInternalException e) {
										// TODO Auto-generated catch block
										MessageDialog.openError(parent.getShell(), "Error", e.getMessage());
									} catch (GitAPIException e) {
										// TODO Auto-generated catch block
										MessageDialog.openError(parent.getShell(), "Error", e.getMessage());
									}
								}
							});
							afterClone(parent.getShell());
						} catch (Exception e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
							// MessageDialog.openError(parent.getShell(),
							// "Error", e1.getMessage());
						}
					}
				}
			}
		});

		createButton(parent, IDialogConstants.CANCEL_ID, i18n.Cancel, false);
		Button help = createButton(parent, IDialogConstants.NO_ID, i18n.Help, false);
		help.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseUp(MouseEvent e) {
				try {
					PlatformUI.getWorkbench().getBrowserSupport().getExternalBrowser()
							.openURL(new URL(RemoteApi.helpUrl));
				} catch (PartInitException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				} catch (MalformedURLException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		});
	}

	private void afterClone(Shell shell) {
		MessageDialog.openInformation(shell, "Info", "Clone done");
		util.addConfiguredRepository(new File(projectPath + Platform.getLocation().SEPARATOR + ".git"));
		IViewPart reps;
		try {
			reps = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
					.showView("org.eclipse.egit.ui.RepositoriesView");
		} catch (PartInitException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		WindowsHandler.cloneWindow.getShell().dispose();
		WindowsHandler.cloneWindow = null;
		Repository rep = null;
		try {
			rep = GitUtil.getRepository(projectPath);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		GitCreateProjectViaWizardWizard wizard = new GitCreateProjectViaWizardWizard(rep, projectPath);
		WizardDialog dialog = new WizardDialog(shell, wizard);
		dialog.create();
		dialog.open();
	}

	/**
	 * Return the initial size of the dialog.
	 */
	@Override
	protected Point getInitialSize() {
		return new Point(483, 229);
	}

	private String getDefaultDirName(String path) {
		return path.split("/")[path.split("/").length - 1].split("\\.")[0];
	}

	private List<Repositories> getRepositoriesArray() throws ClientProtocolException, IOException {
		Repositories repository = new Repositories();// 根节点
		List<String> list = new ArrayList<String>();// Repository列表
		List<Repositories> rep = new ArrayList<Repositories>();// 为接口封装类型
		String cloneType = UserData.getValue("cloneType");
		String url;
		if (cloneType.equals("ssh")) {
			url = "git@git.oschina.net:";
		} else {
			url = "https://git.oschina.net/";
		}
		String response = HttpUtil.get(RemoteApi.getProjects + "?private_token=" + private_token);
		JsonArray jsons = JsonUtil.formatToJsonArray(response);
		for (int i = 0; i < jsons.size(); i++) {
			list.add(url + jsons.get(i).getAsJsonObject().get("path_with_namespace").getAsString() + ".git");
		}
		repository.setName("Repositories");
		repository.setRepositories(list);
		rep.add(repository);
		return rep;
	}
}
